﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Parser;

namespace Genuilder.Extensibility.NRefactory
{
	public class CompilationUnitExtension
	{
		readonly GenItem _Item;
		public CompilationUnitExtension(GenItem item)
		{
			_MustParse = true;
			_Item = item;
			ParseMethodBodies = true;
		}

		bool _MustParse;
		

		CompilationUnit _Unit;
		Errors _Errors;
		public CompilationUnit CompilationUnit
		{
			get
			{
				EnsureParsed();
				return _Unit;
			}
		}

		public bool IsSupported
		{
			get
			{
				if(_Item.Name.EndsWith(".cs", StringComparison.InvariantCultureIgnoreCase))
					return true;
				if(_Item.Name.EndsWith(".vb", StringComparison.InvariantCultureIgnoreCase))
					return true;
				return false;
			}
		}

		public Errors Errors
		{
			get
			{
				EnsureParsed();
				return _Errors;
			}
		}

		private void EnsureParsed()
		{
			if(_MustParse)
			{
				_MustParse = false;
				Parse();
			}
		}


		public void Save()
		{
			var visitor = GetOutputVisitor(_Item.Name);
			CompilationUnit.AcceptVisitor(visitor, null);
			_Item.WriteAllText(visitor.Text);
		}

		private IOutputAstVisitor GetOutputVisitor(string file)
		{
			if(file.EndsWith(".cs"))
				return new CSharpOutputVisitor();
			else if(file.EndsWith(".vb"))
				return new VBNetOutputVisitor();
			else
				return null;
		}

		public bool ParseMethodBodies
		{
			get;
			set;
		}

		private void Parse()
		{
			var parser = ParserFactory.CreateParser(GetLanguage(), new StringReader(_Item.ReadAllText()));
			parser.ParseMethodBodies = ParseMethodBodies;
			parser.Parse();
			_Unit = parser.CompilationUnit;
			_Errors = parser.Errors;
		}

		private SupportedLanguage GetLanguage()
		{
			if(_Item.Name.EndsWith(".cs", StringComparison.InvariantCultureIgnoreCase))
				return SupportedLanguage.CSharp;
			if(_Item.Name.EndsWith(".vb", StringComparison.InvariantCultureIgnoreCase))
				return SupportedLanguage.VBNet;
			throw new NotSupportedException("cannot parse file " + _Item.Name + ", it seems it's not VB nor CSharp");
		}
	}
}
